package service

import (
	"errors"
	"fmt"
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/facade/runtime"
	"gitee.com/sansaniot/ssiot-core/httpmvc/service"
	"gitee.com/sansaniot/ssiot-core/logger"
	"github.com/bytedance/sonic"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"net/url"
	"ssdevice/common/constant"
	"ssdevice/common/cron"
	cDto "ssdevice/common/dto"
	"ssdevice/common/middleware/mqtt"
	"ssdevice/common/utils"
	"ssdevice/internal/device/models"
	"ssdevice/internal/device/models/command"
	"ssdevice/internal/device/models/query"
	"strconv"
	"strings"
	"time"
)

type DeviceTask struct {
	sysOTAPackage *models.SysOTAPackage
	sysBatchTask  *models.SysBatchTask
	sysTaskDevice *models.SysTaskDevice
	service.Service
}

func StartCheckTask() {
	logger.Info("设备批量任务超时检测启动")
	// 定时检查任务超时情况
	cron.AddCronTask("0 * * * * ?", checkTaskTimeOut, false)
	//go ackOtaUpgrade()
}

func checkTaskTimeOut() {
	logger.Info("设备批量任务超时检测执行")
	s := &DeviceTask{}
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return
	}
	s.Orm = db
	s.SetAllModel()
	req := query.SysBatchTaskQuery{}
	req.Status = 1
	if err, result := s.sysBatchTask.FindTaskList(&req); err == nil {
		taskList := result.([]models.SysBatchTask)
		logger.Infof("设备批量任务超时检测,超时任务数量：%d", len(taskList))
		for _, task := range taskList {
			s.CheckTaskTimeOut(task)
		}
	}

}
func ackOtaUpgrade() {
	db := env.Db
	var taskDeviceModel models.SysTaskDevice
	taskDeviceModel = models.SysTaskDevice{}
	taskDeviceModel.Orm = db
	//var count int64
	//count = 0
	for {
		constant.OTACIdMap.IterCb(func(sid string, process int) {

		})
	}
}
func (d *DeviceTask) SetOTAPackageModel(m *models.SysOTAPackage) *DeviceTask {
	d.sysOTAPackage = m
	return d
}

func (d *DeviceTask) SetBatchTaskModel(m *models.SysBatchTask) *DeviceTask {
	d.sysBatchTask = m
	return d
}

func (d *DeviceTask) SetTaskDeviceModel(m *models.SysTaskDevice) *DeviceTask {
	d.sysTaskDevice = m
	return d
}

func (d *DeviceTask) SetAllModel() {
	d.sysOTAPackage = &models.SysOTAPackage{}
	d.sysBatchTask = &models.SysBatchTask{}
	d.sysTaskDevice = &models.SysTaskDevice{}
	d.sysOTAPackage.Orm = d.Orm
	d.sysBatchTask.Orm = d.Orm
	d.sysTaskDevice.Orm = d.Orm
}

// 添加安装包
func (d *DeviceTask) AddPackage(req *command.PackageInsertReq) (err error, otaPackage models.SysOTAPackage) {

	if err = req.Generate(&otaPackage); err != nil {
		return
	}
	if err = d.sysOTAPackage.Add(otaPackage); err != nil {
		return
	}
	return
}

// 编辑安装包
func (d *DeviceTask) ModPackage(req *command.PackageUpdateReq) (err error, otaPackage models.SysOTAPackage) {

	if err = req.Generate(&otaPackage); err != nil {
		return
	}
	if err = d.sysOTAPackage.Mod(otaPackage); err != nil {
		return
	}
	return
}

// 删除安装包
func (d *DeviceTask) DelPackage(req *command.PackageDeleteReq) (err error) {
	delIds := strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")
	if err = d.sysOTAPackage.Delete(&models.SysOTAPackage{}, cDto.MakeCondition(query.SysOTAPackageQuery{IdIn: delIds})); err != nil {
		return err
	}
	return
}

// 添加任务
func (d *DeviceTask) AddBatchTask(req *command.BatchTaskInsertReq) (err error, batchTask models.SysBatchTask) {

	if err = req.Generate(&batchTask); err != nil {
		return
	}
	if err = d.sysBatchTask.Add(batchTask); err != nil {
		return
	}
	return
}

// 编辑任务
func (d *DeviceTask) ModBatchTask(req *command.BatchTaskUpdateReq) (err error, batchTask models.SysBatchTask) {

	if err = req.Generate(&batchTask); err != nil {
		return
	}
	if err = d.sysBatchTask.Mod(batchTask); err != nil {
		return
	}
	return
}

// 删除任务
func (d *DeviceTask) DelBatchTask(req *command.BatchTaskDeleteReq) (err error) {
	delIds := strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")
	if err = d.sysBatchTask.Delete(&models.SysBatchTask{}, cDto.MakeCondition(query.SysBatchTaskQuery{IdIn: delIds})); err != nil {
		return err
	}
	return
}

// 执行任务
func (d *DeviceTask) ExecBatchTask(req *command.BatchTaskExecReq) (err error) {
	exeTaskIds := strings.Split(strings.ReplaceAll(req.Id, " ", ""), ",")
	for _, v := range exeTaskIds {
		var one models.SysBatchTask
		oneReq := query.SysBatchTaskQuery{}
		oneReq.Id = v

		err = d.sysTaskDevice.FindOne(&one, cDto.MakeCondition(oneReq.GetNeedSearch()))

		if err == nil {
			if one.Status == 1 {
				return errors.New("任务在执行中 请稍后执行")
			}
			//更新状态
			one.Status = 1
			err = d.sysTaskDevice.Mod(one)
			if err != nil {
				return err
			}

			if one.TaskType == "setup" {
				err = d.handleChildTaskForSetup(one)
			} else {
				err = d.handleChildTask(one)
			}
			if err != nil {
				return err
			}
		}
	}
	return
}

func (d *DeviceTask) handleChildTask(one models.SysBatchTask) (err error) {
	logger.Infof("开始执行任务，任务id：%s", one.Id)
	// 初始化设备列表 setup类型 导入的时候已经初始化 无需删除
	//删除子设备
	if err = d.sysTaskDevice.Delete(&models.SysTaskDevice{}, cDto.MakeCondition(query.SysTaskDeviceQuery{TaskId: one.Id})); err != nil {
		return err
	}
	logger.Infof("删除子任务完成，任务id：%s", one.Id)
	//根据条件创建子设备
	//updateType := one.UpdateType
	//默认按产品查询
	dev := &models.SysDev{}
	dev.Orm = d.Orm
	devList := make([]models.SysDev, 0)
	//排除下位机 只升级 配置 重启非下位机，目前协议只支持网关 直连设备
	queryReq := query.SysDevQuery{ProductModel: one.ProductId, GatewaySn: ""}
	filters := utils.BytesToMap(one.Filters)
	if filters["sns"] != nil {
		queryReq.SnIn = strings.Split(strings.ReplaceAll(filters["sns"].(string), " ", ""), ",")
	} else {
		if filters["deptId"] != nil {
			queryReq.DeptId = filters["deptId"].(string)
		} else {
			if filters["version"] != nil {
				//TODO 按版本过滤升级设备
			}
		}
	}

	taskType := one.TaskType
	var result map[string]interface{}
	var url string
	var otaPackage models.SysOTAPackage
	if "upgrade" == taskType {
		//查找升级包
		if len(one.PackageId) == 0 {
			return
		}
		packageQuery := query.SysOTAPackageQuery{}
		packageQuery.Id = one.PackageId
		err = d.sysOTAPackage.FindOne(&otaPackage, cDto.MakeCondition(packageQuery.GetNeedSearch()))
		prefix := env.ConfigOperator.GetString("service.device.download-prefix")
		url = prefix + "/api/file/download/" + otaPackage.PackagePath
		// 执行
		if err, result = utils.DownloadFile(url); err != nil {
			return
		}
		logger.Infof("下载升级包完成，升级包id：%s", otaPackage.Id)
	}
	if err = dev.FindList(&devList, cDto.MakeCondition(queryReq)); err != nil {
		return
	}
	logger.Infof("查询设备完成，任务id：%s", one.Id)
	childTaskUpgradeList := make([]models.SysTaskDevice, 0)
	childMqttUpgradeList := make([]map[string]interface{}, 0)
	var x int64
	x = 0
	for _, v := range devList {
		x++
		childTask := models.SysTaskDevice{}
		childTask.TaskId = one.Id
		childTask.DevSn = v.Sn
		childTask.Status = "doing"
		childTask.Id = utils.SimpleUUID()

		now := cDto.LocalTime(time.Now())
		childTask.CreateTime = &now
		childTask.UpdateTime = &now

		//修改sid非uint32
		sid := utils.AtomicAddSid()
		childTask.Sid = int64(sid)

		var topic string
		var contentBytes []byte

		if "upgrade" == taskType {
			// 发送升级mqtt
			content := make(map[string]interface{})
			data := make(map[string]interface{})
			data["type"] = "main"
			data["url"] = url
			data["fileid"] = otaPackage.PackagePath
			data["md5"] = result["md5sum"]
			data["size"] = result["fileSize"]
			content["sid"] = sid
			content["data"] = data
			content["sn"] = v.Sn
			childTaskUpgradeList = append(childTaskUpgradeList, childTask)
			childMqttUpgradeList = append(childMqttUpgradeList, content)
		} else if "restart" == taskType {
			topic = fmt.Sprintf("/iot/%s/%s/func/reboot", v.Sn, constant.TopicPlaceholder)
			content := make(map[string]interface{})
			data := make(map[string]interface{})
			data["input"] = nil
			content["sid"] = sid
			content["data"] = data
			contentBytes, _ = sonic.Marshal(content)
			//新增任务
			if err = d.sysTaskDevice.Add(childTask); err != nil {
				return
			}
			// 发送重启mqtt

			// 下发终端
			// 同步处理, 订阅响应
			subT := fmt.Sprintf("/iot/%s/%s/func/%s/ack", constant.TopicPlaceholder, v.Sn, "reboot")
			// 同步下发
			// 指定超时时间
			overtime := time.Duration(5) * time.Second
			if err = mqtt.MqttClient.SyncSendTimer(topic, contentBytes, sid, overtime, subT, func(msgInfo map[string]interface{}, e *error) {
				//成功回调
				//成功回调  更新任务状态
				now = cDto.LocalTime(time.Now())
				childTask.UpdateTime = &now
				childTask.Status = "done"
				if err = d.sysTaskDevice.Mod(childTask); err != nil {
					return
				}
			}); err != nil {
				//失败回调
				syncSendErrCallback(subT, sid)
				//更新任务状态
				now = cDto.LocalTime(time.Now())
				childTask.UpdateTime = &now
				childTask.Status = "failed"
				if err = d.sysTaskDevice.Mod(childTask); err != nil {
					return
				}
			}
		} else if "config" == taskType {
			topic = fmt.Sprintf("/iot/%s/%s/config/set", v.Sn, constant.TopicPlaceholder)
			content := make(map[string]interface{})
			data := utils.BytesToMap(one.ConfigData)
			content["sid"] = sid
			content["data"] = data
			contentBytes, _ = sonic.Marshal(content)
			//新增任务
			if err = d.sysTaskDevice.Add(childTask); err != nil {
				return
			}
			// 发送配置mqtt

			// 同步处理, 订阅响应  /iot/$/{sn}/config/set/ack
			subT := fmt.Sprintf("/iot/%s/%s/config/set/ack", constant.TopicPlaceholder, v.Sn)
			// 同步下发
			// 指定超时时间
			overtime := time.Duration(5) * time.Second
			if err = mqtt.MqttClient.SyncSendTimer(topic, contentBytes, sid, overtime, subT, func(msgInfo map[string]interface{}, e *error) {
				//成功回调  更新任务状态
				now = cDto.LocalTime(time.Now())
				childTask.UpdateTime = &now
				childTask.Status = "done"
				if err = d.sysTaskDevice.Mod(childTask); err != nil {
					return
				}
			}); err != nil {
				//失败回调
				syncSendErrCallback(subT, sid)
				//更新任务状态
				now = cDto.LocalTime(time.Now())
				childTask.UpdateTime = &now
				childTask.Status = "failed"
				if err = d.sysTaskDevice.Mod(childTask); err != nil {
					return
				}
			}
		}

	}

	if "upgrade" == taskType && len(childTaskUpgradeList) > 0 {
		a := 0 //避免sid重复
		sliceList := chunkSlice(childTaskUpgradeList, 1000)
		var affected int64
		affected = 0
		for _, v := range sliceList {
			count := d.sysTaskDevice.Orm.Create(v).RowsAffected
			affected = affected + count
		}

		logger.Infof("子任务插入完成，插入总数：%d", affected)
		//发送mqtt
		for _, v := range childMqttUpgradeList {
			a++
			sn := v["sn"]
			topic := fmt.Sprintf("/iot/%s/%s/ota/upgrade", sn, constant.TopicPlaceholder)
			v["sn"] = nil
			contentBytes, _ := sonic.Marshal(v)
			//mqtt.MqttClient.Publish(topic, contentBytes)
			//mqtt.MqttClient.GetClient().Publish(topic, 1, true, contentBytes)
			if a%10 == 0 {
				time.Sleep(9)
			}
			if err = mqtt.MqttClient.GetClient().Publish(topic, 1, false, contentBytes).Error(); err != nil {
				logger.Errorf("[%s]消息发布失败,err=%s", topic, err.Error())
			}
		}
		logger.Infof("mqtt发送完成,总数：%d", a)
	}
	return nil
}

// chunkSlice 将一个切片分割成多个大小为chunkSize的子切片
func chunkSlice(slice []models.SysTaskDevice, chunkSize int) [][]models.SysTaskDevice {
	var chunks [][]models.SysTaskDevice
	for i := 0; i < len(slice); i += chunkSize {
		end := i + chunkSize
		if end > len(slice) {
			end = len(slice)
		}
		chunks = append(chunks, slice[i:end])
	}
	return chunks
}
func (d *DeviceTask) handleChildTaskForSetup(one models.SysBatchTask) (err error) {

	// 初始化设备列表 setup类型 导入的时候已经初始化 无需删除
	req := query.SysTaskDeviceQuery{}
	req.TaskId = one.Id
	var queryResult interface{}
	err, queryResult = d.sysTaskDevice.FindTaskDeviceList(&req)
	childTaskList := queryResult.([]models.SysTaskDevice)
	//查询子任务
	for _, v := range childTaskList {
		//查询设备是否存在  不存在则不发消息
		sysDev := models.SysDev{}
		sysDev.Orm = env.Db
		if errDev := sysDev.FindOne(&sysDev, cDto.MakeCondition(query.SysDevQuery{IdSn: v.DevSn})); errDev != nil {
			continue
		}
		if len(sysDev.Sn) == 0 {
			continue
		}
		now := cDto.LocalTime(time.Now())
		v.UpdateTime = &now

		sid := time.Now().UnixNano() / int64(time.Millisecond)
		v.Sid = sid

		var topic string
		var contentBytes []byte

		topic = fmt.Sprintf("/iot/%s/%s/sensor/set", sysDev.GatewaySn, constant.TopicPlaceholder)
		content := make(map[string]interface{})
		data := utils.BytesToMap(v.SetupData)
		content["sid"] = sid
		content["from"] = constant.TopicPlaceholder
		content["to"] = v.DevSn
		content["data"] = data
		contentBytes, _ = sonic.Marshal(content)
		// 发送配置mqtt

		//更新任务
		v.Sid = sid
		if err = d.sysTaskDevice.Mod(v); err != nil {
			return
		}
		//发送mqtt
		mqtt.MqttClient.Publish(topic, contentBytes)
	}
	return nil
}

func (d *DeviceTask) CheckTaskTimeOut(one models.SysBatchTask) (err error) {

	// 检查任务子设备
	queryReq := query.SysTaskDeviceQuery{TaskId: one.Id}
	var result interface{}
	if err, result = d.sysTaskDevice.FindTaskDeviceList(&queryReq); err != nil {
		return err
	}
	childTaskList := result.([]models.SysTaskDevice)
	finishFlag := true
	for _, childTask := range childTaskList {
		// 判断是否超时  超时则改变状态
		createTimeLocal := childTask.CreateTime
		createTime := time.Time(*createTimeLocal)
		nowLocal := cDto.LocalTime(time.Now())
		now := time.Time(nowLocal)
		difference := now.Sub(createTime)

		//执行中子任务  判断是否超时
		if childTask.Status == "doing" {
			if difference.Minutes() > 5 {
				//超时
				childTask.Status = "timeout"
				updateTime := cDto.LocalTime(time.Now())
				childTask.UpdateTime = &updateTime
				d.sysTaskDevice.Mod(childTask)
			} else {
				finishFlag = false
			}
		}

	}
	//修改任务状态 如果所有子任务都为非 doing状态 则任务修改为完成2
	if finishFlag {
		one.Status = 2
		now := cDto.LocalTime(time.Now())
		one.UpdateTime = &now
		d.sysBatchTask.Mod(one)
	}
	return nil
}

// 导出模版
func (d *DeviceTask) ExportSetupTemplate(c *gin.Context, req *query.SysBatchTaskQuery) error {
	// 生成模板
	f := excelize.NewFile()
	defer f.Close()
	// 模板内容
	if err := FillExportTemplate(f); err != nil {
		return err
	}
	// 删除excelize的默认sheet
	f.DeleteSheet("Sheet1")
	// 响应文件流
	fileName := fmt.Sprintf("设备变量.xlsx")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename*=utf-8''%s", url.QueryEscape(fileName)))
	c.Header("File-Name", url.QueryEscape(fileName))
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8")
	if _, err := f.WriteTo(c.Writer); err != nil {
		_, _ = fmt.Fprintf(c.Writer, err.Error())
		return err
	}
	return nil
}

// 导入设备数据下发
func (d *DeviceTask) ImportSetupTask(c *gin.Context, req *query.SysTaskDeviceQuery) error {
	//校验 任务类型是不是setup

	// 获取文件对象
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		return err
	}
	if file == nil || !strings.HasSuffix(header.Filename, ".xlsx") {
		return errors.New("非法文件，请使用正确的文件导入")
	}
	defer file.Close()
	f, err := excelize.OpenReader(file)
	if err != nil {
		return err
	}
	d.sysTaskDevice.TaskId = req.TaskId
	// 执行导入
	if err = ImportSetupData(d.sysTaskDevice, f, req.UserId); err != nil {
		return err
	}
	return nil
}

var (
	SetupHeaderName = []string{"设备", "变量标识", "设置值"}
	SetupHeaderKey  = []string{"sn", "key", "value"}
)

// 导出变量内容填充
func FillExportTemplate(f *excelize.File) error {
	// 头部单元格样式
	headerCellStyle, _ := f.NewStyle(&excelize.Style{
		Font: &excelize.Font{
			Bold: true,
		},
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical:   "center",
		},
		Border: []excelize.Border{
			{Type: "left", Color: "000000", Style: 1},
			{Type: "top", Color: "000000", Style: 1},
			{Type: "bottom", Color: "000000", Style: 1},
			{Type: "right", Color: "000000", Style: 1},
		},
	})
	sheetName := "设置变量"
	_, _ = f.NewSheet(sheetName)
	// 第1行
	_ = f.InsertRows(sheetName, 1, 1)
	colNum := len(SetupHeaderName)
	for n := 0; n < colNum; n++ {
		axis, _ := excelize.ColumnNumberToName(n + 1)
		_ = f.SetCellValue(sheetName, axis+"1", SetupHeaderName[n])
		_ = f.SetCellStyle(sheetName, axis+"1", axis+"1", headerCellStyle)
		_ = f.SetColWidth(sheetName, axis, axis, 20)
	}
	return nil
}

func ImportSetupData(setupTask *models.SysTaskDevice, f *excelize.File, userId string) (err error) {
	sheetNum := f.SheetCount
	if sheetNum == 0 {
		return
	}
	// 解析
	modelMap := make(map[string]models.SysTaskDevice)
	errorInfo := ""
	for _, sheetName := range f.GetSheetList() {
		// 遍历设备
		rowIndexRead := make([]int, 0)
		sheetErrPre := fmt.Sprintf("<br>(sheet: %s)<br>", sheetName)
		headerNames := SetupHeaderName
		headerKeys := SetupHeaderKey
		// 按行获取[][]单元格值，f.Rows迭代器不能过滤掉空内容的行
		var rows, cols [][]string
		rows, err = f.GetRows(sheetName)
		if err != nil {
			fmt.Println(err)
		}
		cols, err = f.GetCols(sheetName)
		if err != nil {
			fmt.Println(err)
		}
		maxRowNumber := len(rows)
		maxColNumber := len(cols)
		if maxRowNumber <= 1 {
			errorInfo += fmt.Sprintf("模板内容为空(sheet:%s)", sheetName)
			continue
		}
		if maxColNumber != len(headerNames) {
			return errors.New("无效的导入文件，请重新导出文件填写内容")
		}
		for rowIndex, rowColumns := range rows {
			if utils.IntIn(rowIndex, rowIndexRead) {
				// 效率优化 (每sheet中 遍历过的行跳过)
				continue
			}
			if rowIndex == 0 {
				rowIndexRead = append(rowIndexRead, rowIndex)
				continue
			}
			// 第2行起 为数据内容 解析行数据
			rowDataParseDto := parseSetupRowData(rowColumns, headerKeys, setupTask.TaskId, modelMap, userId)
			if rowDataParseDto.NotSn {
				continue
			}
			rowIndexRead = append(rowIndexRead, rowIndex)
			errMsg := rowDataParseDto.Error
			if len(errMsg) > 0 {
				tmpErrStr := fmt.Sprintf("第%s行:<br>%s", strconv.Itoa(rowIndex+1), errMsg)
				if !strings.Contains(errorInfo, sheetErrPre) {
					errorInfo += sheetErrPre
				}
				if !strings.Contains(errorInfo, tmpErrStr) {
					errorInfo += tmpErrStr
				}
				continue
			}
			taskDevice := rowDataParseDto.SysTaskDevice
			modelMap[taskDevice.DevSn] = taskDevice
		}
	}
	if len(errorInfo) > 0 {
		return errors.New(errorInfo)
	}
	// 删除任务设备
	if err = setupTask.Delete(&models.SysTaskDevice{}, cDto.MakeCondition(query.SysTaskDeviceQuery{TaskId: setupTask.TaskId})); err != nil {
		return err
	}
	// 插入任务
	for _, v := range modelMap {
		//新增任务
		if err = setupTask.Add(v); err != nil {
			return
		}
	}
	return
}

type RowDataSetupDto struct {
	SysTaskDevice models.SysTaskDevice
	Error         string
	NotSn         bool
}

// 导入变量 - 解析行数据
func parseSetupRowData(rowColumns []string, headerKeys []string, taskId string, modelMap map[string]models.SysTaskDevice, userId string) (rowDataParseDto RowDataSetupDto) {
	errStr := ""
	var taskDeviceModel models.SysTaskDevice
	setupData := make(map[string]interface{})
	maxCol := len(headerKeys)
	length := len(rowColumns)
	var sn string
	var key string
	var value string
	for colIndex := 0; colIndex < maxCol; colIndex++ {
		headerKey := headerKeys[colIndex]
		cellVal := ""
		if colIndex < length {
			cellVal = rowColumns[colIndex]
		}
		cellVal = strings.TrimSpace(cellVal)
		axis, _ := excelize.ColumnNumberToName(colIndex + 1)
		switch headerKey {
		case "sn":
			if len(strings.ReplaceAll(cellVal, " ", "")) == 0 {
				errStr += fmt.Sprintf("%s列-%s<br>", axis, "设备SN(必填)")
				break
			}

			sn = cellVal
			break
		case "key":
			if len(strings.ReplaceAll(cellVal, " ", "")) == 0 {
				errStr += fmt.Sprintf("%s列-%s<br>", axis, "变量标识(必填)")
				break
			}
			key = cellVal
			break
		case "value":
			value = cellVal
			break
		default:
			break
		}
	}
	if modelMap[sn].TaskId != "" { //已经存在该设备的变量
		taskDeviceModel = modelMap[sn]
		setupData = utils.BytesToMap(taskDeviceModel.SetupData)
	} else {
		taskDeviceModel = models.SysTaskDevice{}
		taskDeviceModel.Id = utils.SimpleUUID()
		taskDeviceModel.DevSn = sn
		taskDeviceModel.TaskId = taskId
		taskDeviceModel.Status = "done"
		now := cDto.LocalTime(time.Now())
		taskDeviceModel.CreateTime = &now
		taskDeviceModel.UpdateTime = &now
	}
	setupData[key] = utils.ConvertStrToNumber(value)
	taskDeviceModel.SetupData = utils.MapToBytes(setupData)
	// 返回行解析
	if len(errStr) == 0 {
		// 数据组装返回
		rowDataParseDto = RowDataSetupDto{
			SysTaskDevice: taskDeviceModel,
		}
	} else if len(errStr) > 0 {
		// 错误信息返回
		rowDataParseDto = RowDataSetupDto{
			Error: errStr,
		}
	}
	return
}
